package com.jihui.jihuipicturebackend.manager;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpStatus;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.Method;
import com.jihui.jihuipicturebackend.config.CosClientConfig;
import com.jihui.jihuipicturebackend.exception.BusinessException;
import com.jihui.jihuipicturebackend.exception.ErrorCode;
import com.jihui.jihuipicturebackend.exception.ThrowUtils;
import com.jihui.jihuipicturebackend.model.dto.file.UploadPictureResult;
import com.qcloud.cos.model.PutObjectResult;
import com.qcloud.cos.model.ciModel.persistence.ImageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import static java.lang.Long.parseLong;

@Deprecated // 该类已废弃，请使用CosManager
@Service
@Slf4j
public class FileManager {

    @Resource
    CosClientConfig cosClientConfig;

    @Resource
    CosManager cosManager;

    /**
     * 上传图片
     * @param multipartFile
     * @param uploadPathPrefix
     * @return
     */
    public UploadPictureResult uploadPicture(MultipartFile multipartFile, String uploadPathPrefix){
        // 参数校验
        validateParams(multipartFile, uploadPathPrefix);
        // 上传文件
        String uuid = UUID.randomUUID().toString();
        String fileSuffix = FileUtil.getSuffix(multipartFile.getOriginalFilename());
        String uploadFileName = String.format("%s_%s.%s", uuid, DateUtil.formatDate(new Date()), fileSuffix);
        String uploadPath = String.format("/%s/%s", uploadPathPrefix, uploadFileName);
        File tempFile = null;
        try {
            // 上传文件
            tempFile = File.createTempFile(uploadPath, null);
            multipartFile.transferTo(tempFile);
            PutObjectResult putObjectResult = cosManager.putPictureObject(uploadPath, tempFile);
            // 返回结果
            ImageInfo imageInfo = putObjectResult.getCiUploadResult().getOriginalInfo().getImageInfo();

            UploadPictureResult uploadPictureResult = new UploadPictureResult();
            int picWidth = imageInfo.getWidth();
            int picHeight = imageInfo.getHeight();
            double picScale = NumberUtil.round(picWidth * 1.0 / picHeight, 2).doubleValue();

            uploadPictureResult.setPicName(FileUtil.mainName(multipartFile.getOriginalFilename()));
            uploadPictureResult.setPicWidth(picWidth);
            uploadPictureResult.setPicHeight(picHeight);
            uploadPictureResult.setPicScale(picScale);
            uploadPictureResult.setPicFormat(imageInfo.getFormat());
            uploadPictureResult.setPicSize(FileUtil.size(tempFile));
            uploadPictureResult.setUrl(cosClientConfig.getHost() + "/" + uploadPath);
            return uploadPictureResult;
        } catch (Exception e) {
            log.error("上传文件失败 + {}", e.getMessage());
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "上传文件失败");
        } finally {
            extracted(tempFile);
        }

    }

    public void deletePicture(String key){
        try{
            cosManager.deleteObject(key);
        }catch (Exception e) {
            log.error("删除文件失败 + {}", e.getMessage());
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "删除文件失败");
        }
    }

    /**
     * 删除临时文件
     * @param tempFile
     */
    private void extracted(File tempFile) {
        if (tempFile != null) {
            boolean deleteFile = tempFile.delete();
            if (!deleteFile) {
                log.error("删除临时文件失败 + {}", tempFile.getAbsolutePath());
            }
        }
    }

    /**
     * 校验参数
     * @param multipartFile
     * @param uploadPathPrefix
     */
    public void validateParams(MultipartFile multipartFile, String uploadPathPrefix) {
        // 校验文件是否为空
        ThrowUtils.throwIf(multipartFile == null,new BusinessException(ErrorCode.PARAMS_ERROR,"文件不能为空"));

        // 校验文件大小
        final Integer MAX_FILE_SIZE = 1024 * 1024 * 5; // 5M
        Long fileSize = multipartFile.getSize();
        ThrowUtils.throwIf(fileSize > MAX_FILE_SIZE,
                new BusinessException(ErrorCode.PARAMS_ERROR,"文件大小不能超过5M"));
        // 校验上传路径前缀
        ThrowUtils.throwIf(uploadPathPrefix == null || uploadPathPrefix.isEmpty(),
                new BusinessException(ErrorCode.PARAMS_ERROR,"上传路径前缀不能为空"));
        // 校验文件类型
        String fileSuffix = FileUtil.getSuffix(multipartFile.getOriginalFilename());
        List<String> uploadPathPrefixes = Arrays.asList("jpg", "png", "jpeg", "gif");
        ThrowUtils.throwIf(!uploadPathPrefixes.contains(fileSuffix),
                new BusinessException(ErrorCode.PARAMS_ERROR,"文件类型不正确"));
    }

    /**
     * 通过URL上传图片
     *
     * @param fileUrl
     * @param uploadPathPrefix
     * @return
     */
    public UploadPictureResult UrlUploadPicture(String fileUrl, String uploadPathPrefix){
        // 参数校验
        validateUrlParams(fileUrl, uploadPathPrefix);
        // 上传文件
        String uuid = UUID.randomUUID().toString();
        String fileSuffix = FileUtil.getSuffix(fileUrl);

        String uploadFileName = String.format("%s_%s.%s", uuid, DateUtil.formatDate(new Date()), fileSuffix);
        String uploadPath = String.format("/%s/%s", uploadPathPrefix, uploadFileName);
        File tempFile = null;
        try {
            // 上传文件
            tempFile = File.createTempFile(uploadPath, null);
            HttpUtil.downloadFile(fileUrl, tempFile);

            PutObjectResult putObjectResult = cosManager.putPictureObject(uploadPath, tempFile);
            // 返回结果
            ImageInfo imageInfo = putObjectResult.getCiUploadResult().getOriginalInfo().getImageInfo();

            UploadPictureResult uploadPictureResult = new UploadPictureResult();
            int picWidth = imageInfo.getWidth();
            int picHeight = imageInfo.getHeight();
            double picScale = NumberUtil.round(picWidth * 1.0 / picHeight, 2).doubleValue();

            uploadPictureResult.setPicName(FileUtil.mainName(FileUtil.mainName(fileUrl)));
            uploadPictureResult.setPicWidth(picWidth);
            uploadPictureResult.setPicHeight(picHeight);
            uploadPictureResult.setPicScale(picScale);
            uploadPictureResult.setPicFormat(imageInfo.getFormat());
            uploadPictureResult.setPicSize(FileUtil.size(tempFile));
            uploadPictureResult.setUrl(cosClientConfig.getHost() + "/" + uploadPath);
            return uploadPictureResult;
        } catch (Exception e) {
            log.error("上传文件失败 + {}", e.getMessage());
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "上传文件失败");
        } finally {
            extracted(tempFile);
        }

    }

    private void validateUrlParams(String fileUrl, String uploadPathPrefix) {
        // 校验文件是否为空
        ThrowUtils.throwIf(StrUtil.isBlank(fileUrl),new BusinessException(ErrorCode.PARAMS_ERROR,"文件URL不能为空"));
        // 校验上传路径前缀
        ThrowUtils.throwIf(uploadPathPrefix == null || uploadPathPrefix.isEmpty(),
                new BusinessException(ErrorCode.PARAMS_ERROR,"上传路径前缀不能为空"));
        // 校验URL是否合法
        try {
            new URL(fileUrl);
        } catch (MalformedURLException e) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"文件URL不合法");
        }
        // 校验是否是Http或Https请求
        if (!fileUrl.startsWith("http://") && !fileUrl.startsWith("https://")) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"文件URL必须是Http或Https请求");
        }
        HttpResponse httpResponse = null;
        try {
            // 发送head请求获取文件
            httpResponse = HttpUtil.createRequest(Method.HEAD, fileUrl).execute();
            if (httpResponse.getStatus() != HttpStatus.HTTP_OK) {
                return;
            }
            // 校验文件类型
            String contentType = httpResponse.header("Content-Type");
            final List<String> ALLOWED_CONTENT_TYPES = Arrays.asList("image/jpg", "image/webp","image/png", "image/jpeg", "image/gif");
            ThrowUtils.throwIf(!ALLOWED_CONTENT_TYPES.contains(contentType),
                    new BusinessException(ErrorCode.PARAMS_ERROR,"文件类型不正确"));
            // 校验文件大小
            try {
                long fileSize = parseLong(httpResponse.header("Content-Length"));
                final long MAX_FILE_SIZE = 1024 * 1024 * 2; // 2M
                ThrowUtils.throwIf(fileSize > MAX_FILE_SIZE,
                        new BusinessException(ErrorCode.PARAMS_ERROR,"文件大小不能超过2M"));
            }catch (NumberFormatException e){
                throw new BusinessException(ErrorCode.PARAMS_ERROR,"文件大小不正确");
            }
        }finally {
            // 关闭流
            if (httpResponse != null){
                httpResponse.close();
            }
        }
    }
}
